package com.itclass.auth.authentication.token;

import lombok.Getter;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticatedPrincipal;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Supplier;

public abstract class AbstractAuthenticationToken<T> implements Authentication ,Serializable  {
    public static final String ROLE = "ROLE_";
    /**
     * 用户认证信息
     */
    protected T details;

    /**
     * 是否认证
     */
    protected boolean authenticated = false;

    protected Collection<GrantedAuthority> authorities;
    public AbstractAuthenticationToken(boolean authenticated) {
        this.authenticated = authenticated;
    }

    @Getter
    private Supplier<T> supplier;

    public T getDetails() {
        // 不会存在并发问题，所以不用加锁之类的
        if (details == null) {
            details = supplier.get();
        }
        return details;
    }
    public void setAuthorities(List<String> authorities) {
        if (!CollectionUtils.isEmpty(authorities)) {
            List<GrantedAuthority> authoritiesList = new ArrayList<>();
            for (String authority : authorities) {
                authoritiesList.add(new SimpleGrantedAuthority(ROLE + authority));
            }
            this.authorities = authoritiesList;
        }
    }
    public void setAuthoritiesRoles(List<String> authorities) {
        if (!CollectionUtils.isEmpty(authorities)) {
            List<GrantedAuthority> authoritiesList = new ArrayList<>();
            for (String authority : authorities) {
                authoritiesList.add(new SimpleGrantedAuthority(authority));
            }
            this.authorities = authoritiesList;
        }
    }
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }
    @Override
    public boolean isAuthenticated() {
        return this.authenticated;
    }

    @Override
    public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
        this.authenticated = isAuthenticated;
    }

    public void setDetails(T details) {
        this.details = details;
    }

    public void setSupplier(Supplier<T> supplier) {
        this.supplier = supplier;
    }

    @Override
    public String getName() {
        if (this.getPrincipal() instanceof UserDetails) {
            return ((UserDetails) this.getPrincipal()).getUsername();
        }
        if (this.getPrincipal() instanceof AuthenticatedPrincipal) {
            return ((AuthenticatedPrincipal) this.getPrincipal()).getName();
        }
        if (this.getPrincipal() instanceof Principal) {
            return ((Principal) this.getPrincipal()).getName();
        }
        return (this.getPrincipal() == null) ? "" : this.getPrincipal().toString();
    }

}
